home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 23
/
AACD 23.iso
/
AACD
/
Online
/
opennap
/
hashlist.c
< prev
next >
Wrap
C/C++ Source or Header
|
2001-06-08
|
4KB
|
192 lines
/* Copyright (C) 2000-1 drscholl@users.sourceforge.net
This is free software distributed under the terms of the
GNU Public License. See the file COPYING for details.
$Id: hashlist.c,v 1.8 2001/02/15 08:39:45 drscholl Exp $ */
#include <stdlib.h>
#include <string.h>
#include "list.h"
#include "hash.h"
#include "hashlist.h"
#include "opennap.h"
#include "debug.h"
hashlist_t *
hashlist_add (HASH * h, void *key, void *data)
{
hashlist_t *hl;
ASSERT (key != 0);
hl = hash_lookup (h, key);
if (!hl)
{
hl = CALLOC (1, sizeof (hashlist_t));
if (!hl)
{
OUTOFMEMORY ("hashlist_add");
return 0;
}
#if DEBUG
hl->magic = MAGIC_HASHLIST;
#endif
/* TODO: this should probably be user-configurable */
if (h->hash_key == hash_string)
{
hl->key = STRDUP (key);
if (!hl->key)
{
OUTOFMEMORY ("hashlist_add");
memset (hl, 0xff, sizeof (hashlist_t));
FREE (hl);
return 0;
}
}
else
hl->key = key;
if (hash_add (h, hl->key, hl))
{
FREE (hl->key);
memset (hl, 0xff, sizeof (hashlist_t));
FREE (hl);
return 0;
}
}
ASSERT (hashlist_validate (hl));
if (data)
{
LIST *list;
if (list_find (hl->list, data))
{
/* already present */
return 0;
}
list = MALLOC (sizeof (LIST));
if (!list)
{
OUTOFMEMORY ("hashlist_add");
if (hl->count == 0)
{
ASSERT (hl->list == 0);
hash_remove (h, hl->key);
}
if (h->hash_key == hash_string)
FREE (hl->key);
memset (hl, 0xff, sizeof (hashlist_t));
FREE (hl);
return 0;
}
list->data = data;
hl->list = list_push (hl->list, list);
}
hl->count++;
return hl;
}
int
hashlist_remove (HASH * h, void *key, void *data)
{
hashlist_t *hl;
ASSERT (key != 0);
if ((hl = hash_lookup (h, key)) == 0)
return -1;
ASSERT (hashlist_validate (hl));
ASSERT (hl->count > 0);
if (data)
{
LIST **cur;
LIST *tmp = 0;
ASSERT (hl->list != 0);
/* don't use list_delete() here since we need to ensure that
* the member was actually part of the list in order to
* succeed.
*/
for (cur = &hl->list; *cur;)
{
if ((*cur)->data == data)
{
tmp = *cur;
*cur = (*cur)->next;
FREE (tmp);
break;
}
cur = &(*cur)->next;
}
if (!tmp)
{
/* element was not found on the list */
return -1;
}
}
hl->count--;
if (hl->count == 0)
{
ASSERT (hl->list == NULL);
hash_remove (h, hl->key);
if (h->hash_key == hash_string)
FREE (hl->key);
/* for debugging.. */
memset (hl, 0xff, sizeof (hashlist_t));
FREE (hl);
}
return 0;
}
int
hashlist_count (HASH * h, void *key)
{
hashlist_t *hl;
ASSERT (key != 0);
hl = hash_lookup (h, key);
#if DEBUG
if (hl)
ASSERT (hashlist_validate (hl));
#endif
return (hl ? hl->count : 0);
}
LIST *
hashlist_lookup (HASH * h, void *key)
{
hashlist_t *hl;
ASSERT (key != 0);
hl = hash_lookup (h, key);
#if DEBUG
if (hl)
ASSERT (hashlist_validate (hl));
#endif
return hl ? hl->list : 0;
}
void
hashlist_free (hashlist_t * l)
{
ASSERT (hashlist_validate (l));
/* TODO: currently this should only be called for hash tables which end
* up with leftover entries AND use strings as hash keys
*/
FREE (l->key);
FREE (l);
}
#if DEBUG
int
hashlist_validate (hashlist_t * l)
{
ASSERT_RETURN_IF_FAIL (VALID_LEN (l, sizeof (hashlist_t)), 0);
ASSERT_RETURN_IF_FAIL (l->magic == MAGIC_HASHLIST, 0);
/* if there are members of the list, the count should be greater than
* zero. nonzero count with null list is allowed.
*/
ASSERT_RETURN_IF_FAIL ((l->list && l->count > 0) || l->list == 0, 0);
return 1;
}
#endif